import { Injectable, Logger } from "@nestjs/common";
import { CasinoUnifiedRoundService } from "./services/casino-unified-round.service";
import { CasinoBetService } from "./services/casino-bet.service";
import { CasinoSettlementService } from "./services/casino-settlement.service";
import { CasinoDiceRoundService } from "./services/casino-dice-round.service";
import { CasinoChibiRoundService } from "./services/casino-chibi-round.service";
import { GameType } from "./entities";
import { casinoConfig } from "./config/casino.config";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { CasinoChibiBet } from "./entities/casino-chibi-bet.entity";
import { CasinoChibiRound } from "./entities/casino-chibi-round.entity";
import { CasinoRockPaperScissors } from "./entities/casino-rock-paper-scissors.entity";
import { getBetTypeName } from "./enums/bet-type-mapping.enum";

@Injectable()
export class CasinoService {
  private readonly logger = new Logger(CasinoService.name);

  constructor(
    private readonly roundService: CasinoUnifiedRoundService,
    private readonly betService: CasinoBetService,
    private readonly settlementService: CasinoSettlementService,
    private readonly diceRoundService: CasinoDiceRoundService,
    private readonly chibiRoundService: CasinoChibiRoundService,
    @InjectRepository(CasinoChibiBet)
    private readonly chibiBetRepository: Repository<CasinoChibiBet>,
    @InjectRepository(CasinoChibiRound)
    private readonly chibiRoundRepository: Repository<CasinoChibiRound>,
    @InjectRepository(CasinoRockPaperScissors)
    private readonly rpsRepository: Repository<CasinoRockPaperScissors>
  ) {}

  // 统一计算剩余秒数：非下注中状态返回0，其他返回向上取整的秒数
  private computeRemainingSeconds(endTime: Date, status?: number): number {
    try {
      if (status !== undefined && status !== 0) {
        return 0;
      }

      const nowMs = Date.now();
      const endMs = new Date(endTime).getTime();
      const diffMs = endMs - nowMs;

      // 边界检查：如果剩余时间超过10分钟（600秒），可能是时间设置有问题
      if (diffMs > 600 * 1000) {
        console.warn(
          `⚠️ 警告: 剩余时间${Math.ceil(
            diffMs / 1000
          )}秒超过10分钟，可能存在时间设置问题`
        );
      }

      if (diffMs <= 0) return 0;
      return Math.ceil(diffMs / 1000);
    } catch (error) {
      console.error("❌ 计算剩余秒数失败:", error);
      return 0;
    }
  }

  private formatDateTimeLocal(date: Date): string {
    const pad = (n: number, w = 2) => String(n).padStart(w, "0");
    const y = date.getFullYear();
    const M = pad(date.getMonth() + 1);
    const d = pad(date.getDate());
    const h = pad(date.getHours());
    const m = pad(date.getMinutes());
    const s = pad(date.getSeconds());
    const ms = String(date.getMilliseconds()).padStart(3, "0");
    return `${y}-${M}-${d} ${h}:${m}:${s}.${ms}`;
  }

  // ==================== 大小玩法接口 ====================

  /**
   * 获取大小玩法信息 (act_id: 1332)
   */
  async getDiceGameInfo() {
    try {
      const currentRound = await this.roundService.getCurrentRound(
        GameType.DICE
      );
      if (!currentRound) {
        throw new Error("当前没有可下注的期数");
      }

      const lastRound = await this.diceRoundService.getHistoryRounds(0, 1);
      const lastRoundData = lastRound.rounds[0];

      // 获取当前期数的下注统计信息
      const currentRoundStats = await this.roundService.getRoundBetStatistics(
        currentRound.id,
        GameType.DICE
      );

      this.logger.log(
        `📊 获取期数 ${currentRound.id} 下注统计:`,
        currentRoundStats
      );

      // 解析上期开奖结果
      let prenum1 = 0,
        prenum2 = 0,
        prenum3 = 0;
      if (lastRoundData) {
        prenum1 = lastRoundData.num1 || 0;
        prenum2 = lastRoundData.num2 || 0;
        prenum3 = lastRoundData.num3 || 0;
      }

      return {
        act_id: 1332,
        code: 0,
        data: {
          id: currentRound.id, // 使用ID作为期数标识
          m: 25,
          prenum1: prenum1,
          prenum2: prenum2,
          prenum3: prenum3,
          presumgold: lastRoundData?.totalGold || 0,
          presumsliver: lastRoundData?.totalSilver || 0,
          second: this.computeRemainingSeconds(
            currentRound.endTime,
            currentRound.status
          ),
          list: [],
          state: currentRound.status,
          sumbaozigold: currentRoundStats.sumbaozigold,
          sumbaozisliver: currentRoundStats.sumbaozisliver,
          sumdagold: currentRoundStats.sumdagold,
          sumdasliver: currentRoundStats.sumdasliver,
          sumdangold: currentRoundStats.sumdangold,
          sumdansliver: currentRoundStats.sumdansliver,
          sumshuanggold: currentRoundStats.sumshuanggold,
          sumshuangsliver: currentRoundStats.sumshuangsliver,
          sumxiaogold: currentRoundStats.sumxiaogold,
          sumxiaosliver: currentRoundStats.sumxiaosliver,
          time: this.formatDateTimeLocal(currentRound.startTime),
        },
      };
    } catch (error: any) {
      this.logger.error("获取大小玩法信息失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 大小玩法下注 (act_id: 1336)
   */
  async placeDiceBet(userId: number, betData: any) {
    try {
      // 确保 betData 包含必要的字段
      const diceBetData = {
        userId: userId,
        characterId: betData.characterId || 0,
        betType: betData.betType,
        betAmount: Number(betData.betAmount),
        currencyType: betData.currencyType,
      };

      const result = await this.betService.placeDiceBet(diceBetData);
      return {
        act_id: 1336,
        code: 0,
        msg: "下注成功",
      };
    } catch (error: any) {
      this.logger.error("大小玩法下注失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取大小玩法历史 (act_id: 1338)
   */
  async getDiceHistory(page: number = 0) {
    try {
      // 直接使用diceRoundService获取历史期数
      const history = await this.diceRoundService.getHistoryRounds(page, 20);

      // 根据标准指令说明返回正确的数据格式
      const formattedHistory = history.rounds.map((round: any) => {
        // 安全处理日期字段，避免 Invalid time value 错误
        let creationDate = "";
        let durationSeconds = 0;

        try {
          if (
            round.endTime &&
            round.endTime instanceof Date &&
            !isNaN(round.endTime.getTime())
          ) {
            creationDate = round.endTime
              .toISOString()
              .replace("T", " ")
              .replace("Z", "");
          } else if (round.endTime) {
            const date = new Date(round.endTime);
            if (!isNaN(date.getTime())) {
              creationDate = date
                .toISOString()
                .replace("T", " ")
                .replace("Z", "");
            }
          }

          // 计算期数时长
          if (round.startTime && round.endTime) {
            const startTime =
              round.startTime instanceof Date
                ? round.startTime
                : new Date(round.startTime);
            const endTime =
              round.endTime instanceof Date
                ? round.endTime
                : new Date(round.endTime);
            if (!isNaN(startTime.getTime()) && !isNaN(endTime.getTime())) {
              durationSeconds = Math.floor(
                (endTime.getTime() - startTime.getTime()) / 1000
              );
            }
          }
        } catch (error) {
          this.logger.warn(`处理期数 ${round.id} 的时间字段失败:`, error);
          creationDate = new Date()
            .toISOString()
            .replace("T", " ")
            .replace("Z", "");
        }

        return {
          creationdate: creationDate,
          id: round.id, // 使用ID作为期数标识
          m: round.totalBets || 0,
          prenum1: round.num1 || 0,
          prenum2: round.num2 || 0,
          prenum3: round.num3 || 0,
          presumgold: round.totalGold || 0,
          presumsliver: round.totalSilver || 0,
          second: durationSeconds,
          state: round.status === 2 ? 1 : 0, // 只有已结算(SETTLED=2)状态返回1，其他都返回0
          sumbaozigold: round.totalGold || 0,
          sumbaozisliver: round.totalSilver || 0,
          sumdagold: round.totalGold || 0,
          sumdangold: round.totalGold || 0,
          sumdansliver: round.totalSilver || 0,
          sumdasliver: round.totalGold || 0,
          sumonepairgold: round.totalGold || 0,
          sumonepairsliver: round.totalSilver || 0,
          sumshuanggold: round.totalGold || 0,
          sumshuangsliver: round.totalSilver || 0,
          sumxiaogold: round.totalGold || 0,
          sumxiaosliver: round.totalSilver || 0,
        };
      });

      return {
        act_id: 1338,
        code: 0,
        list: formattedHistory,
      };
    } catch (error: any) {
      this.logger.error("获取大小玩法历史失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取我的大小玩法下注 (act_id: 1339)
   */
  async getDiceMyBets(characterId: number, pageNum: number = 0) {
    try {
      // 使用连接查询，一次性获取下注记录和期数信息，避免N+1查询问题
      // 标准格式：pageNum从0开始，每页20条
      const bets = await this.betService.getUserDiceBetsWithRoundInfo(
        characterId,
        pageNum,
        20 // 标准分页大小
      );

      // 根据标准指令说明返回正确的数据格式
      const formattedBets = bets.bets.map((bet: any) => {
        // 安全处理日期字段，避免 Invalid time value 错误
        let creationDate = "";
        try {
          if (
            bet.created_at &&
            bet.created_at instanceof Date &&
            !isNaN(bet.created_at.getTime())
          ) {
            creationDate = bet.created_at
              .toISOString()
              .replace("T", " ")
              .replace("Z", "");
          } else if (bet.created_at) {
            // 如果是字符串，尝试解析
            const date = new Date(bet.created_at);
            if (!isNaN(date.getTime())) {
              creationDate = date
                .toISOString()
                .replace("T", " ")
                .replace("Z", "");
            }
          }
        } catch (error) {
          this.logger.warn(`处理下注记录 ${bet.id} 的创建时间失败:`, error);
          creationDate = new Date()
            .toISOString()
            .replace("T", " ")
            .replace("Z", "");
        }

        return {
          creation_date: creationDate,
          descr: `${this.getBetTypeDescription(bet.betType)}${bet.betAmount}${
            bet.currencyType === 1 ? "金" : "银"
          },${
            bet.status === 0
              ? "未开奖"
              : bet.status === 1
              ? "结算中"
              : bet.status === 2 && bet.winAmount > 0
              ? "赢" + bet.winAmount + (bet.currencyType === 1 ? "金" : "银两")
              : "输局"
          }!`,
          game_id: bet.roundId, // 直接使用 roundId 作为期数标识
          gold: bet.currencyType === 1 ? Number(bet.betAmount) : 0,
          id: bet.id,
          sliver: bet.currencyType === 2 ? Number(bet.betAmount) : 0,
          status: bet.status === 2 && bet.winAmount > 0 ? 1 : 0,
          type: bet.currencyType === 1 ? 0 : 1,
        };
      });

      return {
        act_id: 1339,
        code: 0,
        list: formattedBets,
      };
    } catch (error: any) {
      this.logger.error("获取我的大小玩法下注失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取大小玩法中奖名单 (act_id: 5280)
   */
  async getDiceWinners(pageNum: number = 0) {
    try {
      // 查询最近一期已开奖的大小玩法期数
      const latestSettledRound = await this.roundService.getLatestSettledRound(
        GameType.DICE
      );

      if (!latestSettledRound) {
        return {
          act_id: 5280,
          code: 0,
          list: [],
        };
      }

      // 查询该期数中奖的下注记录
      const winningBets = await this.betService.getDiceWinningBets(
        latestSettledRound.id,
        pageNum,
        20 // 每页20条记录
      );

      // 格式化中奖名单数据，按照用户要求的格式
      const winnerList = winningBets.bets.map((bet: any) => {
        // 根据下注类型和货币类型反向映射为1336指令的type值
        let type = 0;
        switch (bet.betType) {
          case 1: // BIG
            type = bet.currencyType === 1 ? 3 : 4; // 大金子=3, 大银子=4
            break;
          case 2: // SMALL
            type = bet.currencyType === 1 ? 1 : 2; // 小金子=1, 小银子=2
            break;
          case 3: // ODD
            type = bet.currencyType === 1 ? 7 : 8; // 单金子=7, 单银子=8
            break;
          case 4: // EVEN
            type = bet.currencyType === 1 ? 9 : 10; // 双金子=9, 双银子=10
            break;
          case 5: // TRIPLE
            type = bet.currencyType === 1 ? 5 : 6; // 豹子金子=5, 豹子银子=6
            break;
          default:
            type = 0;
        }

        // 确保数字字段为数字类型
        const winAmount = Number(bet.winAmount) || 0;
        const characterId = Number(bet.characterId) || 0;
        const currencyType = Number(bet.currencyType) || 1;

        return {
          bonus: winAmount, // 中奖金额
          gold: currencyType === 1 ? bet.betAmount : 0, // 金币下注金额
          id: characterId, // 角色ID
          name: bet.characterName || `玩家${characterId}`, // 角色名称
          sliver: currencyType === 2 ? bet.betAmount : 0, // 银币下注金额
          type: type, // 下注类型
        };
      });

      return {
        act_id: 5280,
        code: 0,
        list: winnerList,
      };
    } catch (error: any) {
      this.logger.error("获取大小玩法中奖名单失败:", error?.message || error);
      throw error;
    }
  }

  // ==================== 赤壁玩法接口 ====================

  /**
   * 获取赤壁玩法信息 (act_id: 4430)
   */
  async getChibiGameInfo() {
    try {
      const currentRound = await this.roundService.getCurrentRound(
        GameType.CHIBI
      );
      if (!currentRound) {
        throw new Error("当前没有可下注的期数");
      }

      const lastRound = await this.chibiRoundService.getHistoryRounds(0, 1);
      const lastRoundData = lastRound.rounds[0];

      // 聚合当前期数各阵营下注情况，生成标准list
      const rows = await this.chibiBetRepository
        .createQueryBuilder("bet")
        .select([
          "bet.side AS side",
          "SUM(bet.betGold) AS gold",
          "SUM(bet.betSilver) AS sliver",
        ])
        .where("bet.roundId = :rid", { rid: currentRound.id })
        .groupBy("bet.side")
        .getRawMany();

      // 规范化list输出（按side=1,2,3顺序补齐不存在项为0）
      const sideToRow: Record<
        number,
        { side: number; gold: number; sliver: number }
      > = {
        1: { side: 1, gold: 0, sliver: 0 },
        2: { side: 2, gold: 0, sliver: 0 },
        3: { side: 3, gold: 0, sliver: 0 },
      };
      for (const r of rows) {
        const side = Number(r.side);
        sideToRow[side] = {
          side,
          gold: Number(r.gold) || 0,
          sliver: Number(r.sliver) || 0,
        };
      }
      const list = [sideToRow[1], sideToRow[2], sideToRow[3]];

      // 读取reportStr（若当前回合尚无则为空字符串）
      const chibiRoundEntity = await this.chibiRoundRepository.findOne({
        where: { id: currentRound.id },
      });
      const reportStr =
        chibiRoundEntity?.reportStr || lastRoundData?.reportStr || "";

      return {
        act_id: 4430,
        code: 0,
        data: {
          curRndNum: currentRound.id, // 使用ID作为期数标识
          list,
          preSide: lastRoundData?.winningSide || 0,
          reportStr,
          second: this.computeRemainingSeconds(
            currentRound.endTime,
            currentRound.status
          ),
        },
      };
    } catch (error: any) {
      this.logger.error("获取赤壁玩法信息失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 赤壁玩法下注 (act_id: 4437)
   */
  async placeChibiBet(userId: number, betData: any) {
    try {
      // 转换参数格式
      const chibiBetData = {
        userId: userId,
        characterId: betData.characterId || 0,
        side: betData.side,
        betGold: betData.type === "1" ? betData.bet : 0, // 1=金子
        betSilver: betData.type === "2" ? betData.bet : 0, // 2=银子
      };

      const result = await this.betService.placeChibiBet(chibiBetData);
      return {
        act_id: 4437,
        code: 0,
        msg: "下注成功",
      };
    } catch (error: any) {
      this.logger.error("赤壁玩法下注失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取赤壁玩法获胜者 (act_id: 5281)
   */
  async getChibiWinners(page: number = 0) {
    try {
      // 查询最近一期已开奖的赤壁玩法期数
      const latestSettledRound = await this.roundService.getLatestSettledRound(
        GameType.CHIBI
      );

      if (!latestSettledRound) {
        return {
          act_id: 5281,
          code: 0,
          list: [],
        };
      }

      // 查询该期数中奖的下注记录
      const winningBets = await this.betService.getChibiWinningBets(
        latestSettledRound.id,
        page,
        20 // 每页20条记录
      );

      // 格式化中奖名单数据，按照标准格式
      const winnerList = winningBets.bets.map((bet: any) => {
        // 确保数字字段为数字类型
        const characterId = Number(bet.characterId) || 0;
        const betGold = Number(bet.betGold) || 0;
        const betSilver = Number(bet.betSilver) || 0;
        const winGold = Number(bet.winGold) || 0;
        const winSilver = Number(bet.winSilver) || 0;

        return {
          bonusGold: winGold,
          bonusSliver: winSilver,
          gold: betGold,
          name: bet.characterName || `角色${characterId}`,
          roleId: characterId,
          side: bet.side,
          sliver: betSilver,
        };
      });

      return {
        act_id: 5281,
        code: 0,
        list: winnerList,
      };
    } catch (error: any) {
      this.logger.error("获取赤壁玩法获胜者失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取赤壁玩法历史 (act_id: 4434/4430)
   */
  async getChibiHistory(page: number = 0) {
    try {
      // 直接使用chibiRoundService获取历史期数
      const history = await this.chibiRoundService.getHistoryRounds(page, 50);

      // 将数据库字段映射到标准格式
      const mappedList = (history.rounds || []).map((round) => {
        return {
          creationTime: round.endTime
            ? new Date(round.endTime)
                .toLocaleString("zh-CN", {
                  year: "numeric",
                  month: "2-digit",
                  day: "2-digit",
                  hour: "2-digit",
                  minute: "2-digit",
                  second: "2-digit",
                })
                .replace(/\//g, "-") + ".0"
            : "",
          gold: 0, // 标准格式中gold字段为0
          result: round.winningSide || 0,
          rndNum: round.id || 0,
          sliver: 0, // 标准格式中sliver字段为0
        };
      });

      return {
        act_id: 4434, // 保持与原有4434指令一致
        code: 0,
        list: mappedList,
      };
    } catch (error: any) {
      this.logger.error("获取赤壁玩法历史失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取赤壁玩法动态信息 (act_id: 4430) - 专门处理4430指令
   */
  async getChibiHistoryFor4430(page: number = 0) {
    try {
      // 直接查询casino_chibi_rounds中状态为0（下注中）的最后一期
      const currentRound = await this.chibiRoundRepository.findOne({
        where: { status: 0 },
        order: { id: "DESC" },
      });
      if (!currentRound) {
        throw new Error("当前没有可下注的期数");
      }

      // 计算剩余秒数
      const remainingSeconds = this.computeRemainingSeconds(
        currentRound.endTime,
        currentRound.status
      );

      // 构建战报描述 - preSide随机生成
      const preSide = Math.floor(Math.random() * 3) + 1; // 1-3随机
      const reportStr = this.generateChibiReport(preSide);

      // 直接从实体字段构建下注统计列表
      const betList = [
        {
          gold: currentRound.weiTotalGold || 0,
          side: 1, // 魏国
          sliver: currentRound.weiTotalSilver || 0,
        },
        {
          gold: currentRound.shuTotalGold || 0,
          side: 2, // 蜀国
          sliver: currentRound.shuTotalSilver || 0,
        },
        {
          gold: currentRound.wuTotalGold || 0,
          side: 3, // 吴国
          sliver: currentRound.wuTotalSilver || 0,
        },
      ];

      return {
        act_id: 4430,
        code: 0,
        data: {
          curRndNum: currentRound.id,
          list: betList,
          preSide: preSide,
          reportStr: reportStr,
          second: remainingSeconds,
        },
      };
    } catch (error: any) {
      this.logger.error("获取赤壁玩法动态信息失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取我的赤壁玩法下注 (act_id: 4435)
   */
  async getChibiMyBets(userId: number, page: number = 0) {
    try {
      const bets = await this.betService.getUserBets(
        userId,
        GameType.CHIBI,
        page
      );

      // 将数据库字段映射到标准格式
      const mappedList = (bets.bets || []).map((bet) => ({
        bonusGold: Number(bet.winGold) || 0,
        bonusSliver: Number(bet.winSilver) || 0,
        creation_date: bet.created_at
          ? new Date(bet.created_at)
              .toLocaleString("zh-CN", {
                year: "numeric",
                month: "2-digit",
                day: "2-digit",
                hour: "2-digit",
                minute: "2-digit",
                second: "2-digit",
              })
              .replace(/\//g, "-")
          : "",
        creation_time: bet.created_at ? new Date(bet.created_at).getTime() : 0,
        gold: Number(bet.betGold) || 0,
        result:
          bet.status === 2
            ? Number(bet.winGold) > 0 || Number(bet.winSilver) > 0
              ? 1
              : 0
            : 0,
        rndNum: bet.roundId || 0,
        roleId: bet.characterId || 0,
        side: bet.side || 0,
        sliver: Number(bet.betSilver) || 0,
        wagerId: 0,
      }));

      const result = {
        act_id: 4435,
        code: 0,
        list: mappedList,
      };

      return result;
    } catch (error: any) {
      this.logger.error("获取我的赤壁玩法下注失败:", error?.message || error);
      throw error;
    }
  }

  // ==================== 美人计玩法接口 ====================

  /**
   * 创建美人计挑战 (act_id: 2110)
   */
  /**
   * 创建美人计挑战 (act_id: 2110)
   * @param challengerId 角色ID/用户ID
   * @param challengeData 入参对象
   *  - value: 出拳(1石头/2剪刀/3布) 或 challengerValue
   *  - bet: 下注金额 或 betAmount
   *  - type: 币种(1金币/2银币) 或 currencyType
   *  - challengerName: 发起者名称(可选)
   */
  async createRockPaperScissors(
    challengerId: number,
    challengeData: {
      value?: number | string;
      bet?: number | string;
      type?: number | string;
      challengerValue?: number | string;
      betAmount?: number | string;
      currencyType?: number | string;
      challengerName?: string;
    }
  ) {
    try {
      const result = await this.betService.initiateChallenge(
        challengerId,
        challengeData.challengerName || "挑战者",
        // 兼容客户端字段：value, type(1金2银), bet
        Number(challengeData.challengerValue ?? challengeData.value),
        Number(challengeData.betAmount ?? challengeData.bet),
        Number(challengeData.currencyType ?? challengeData.type ?? 1)
      );
      // 与标准返回对齐：成功仅返回 msg
      return {
        act_id: 2110,
        code: 0,
        msg: "创建成功",
      };
    } catch (error: any) {
      this.logger.error("创建美人计挑战失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取美人计挑战列表 (act_id: 2103)
   */
  async getRPSChallenges(page: number = 0) {
    try {
      const challengesData = await this.betService.getRPSChallenges(page);
      // 与标准返回对齐：直接返回 list 数组
      const list = (challengesData.challenges || []).map((c: any) => ({
        id: c.id,
        name: c.challengerName,
        bet: c.betAmount,
        type: c.currencyType,
        userId: c.challengerId,
      }));
      return {
        act_id: 2103,
        code: 0,
        list,
      };
    } catch (error: any) {
      this.logger.error("获取美人计挑战列表失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 响应美人计挑战 (act_id: 2111)
   */
  /**
   * 响应美人计挑战 (act_id: 2111)
   * @param selectedCharacterId 当前选择的角色ID
   * @param challengeId 挑战ID
   * @param responseData 响应数据，包含角色名称和出拳值
   */
  async respondToChallenge(
    selectedCharacterId: number,
    challengeId: number,
    responseData: {
      challengeId: number;
      responderId: number;
      responderName: string;
      responderValue: number;
    }
  ) {
    try {
      const result = await this.betService.respondToChallenge(
        selectedCharacterId,
        responseData
      );

      // 计算应战者的结果：1输了 2赢了 3平局
      let gameResult = 3; // 默认平局

      if (result.challengerValue !== result.responderValue) {
        // 判断应战者是否获胜
        const responderWin =
          (result.responderValue === 1 && result.challengerValue === 2) || // 石头胜剪刀
          (result.responderValue === 2 && result.challengerValue === 3) || // 剪刀胜布
          (result.responderValue === 3 && result.challengerValue === 1); // 布胜石头

        gameResult = responderWin ? 2 : 1; // 2赢了 1输了
      }

      return {
        act_id: 2111,
        code: 0,
        data: gameResult,
      };
    } catch (error: any) {
      this.logger.error("响应美人计挑战失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取美人计挑战记录 (act_id: 2105)
   */
  async getRPSChallengeRecords(selectedCharacterId: number, page: number = 0) {
    try {
      const pageSize = 10;
      const offset = page * pageSize;

      // 查询用户发起的猜拳挑战记录（已完成的）
      const [challenges, total] = await this.rpsRepository.findAndCount({
        where: {
          challengerId: selectedCharacterId,
          status: 2, // COMPLETED状态
        },
        order: { created_at: "DESC" },
        skip: offset,
        take: pageSize,
      });

      // 转换数据格式以匹配前端期望的格式
      const records = challenges.map((challenge) => ({
        answer_id: challenge.responderId || 0,
        bet: challenge.betAmount,
        id: challenge.id,
        name: challenge.responderName || "未知应战者",
        state: this.getChallengeResultState(challenge),
        type: challenge.currencyType,
      }));

      return {
        act_id: 2105,
        code: 0,
        data: {
          list: records,
          total,
          page,
          pageSize,
        },
      };
    } catch (error: any) {
      this.logger.error("获取美人计挑战记录失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取挑战结果状态
   */
  private getChallengeResultState(challenge: CasinoRockPaperScissors): number {
    if (!challenge.isCompleted || !challenge.hasWinner) {
      return 0; // 未完成
    }

    // 如果挑战者获胜，返回1；如果应战者获胜，返回2
    return challenge.winnerId === challenge.challengerId ? 1 : 2;
  }

  /**
   * 获取美人计响应记录 (act_id: 2106)
   */
  async getRPSResponseRecords(userId: number, page: number = 0) {
    try {
      const pageSize = 10;
      const offset = page * pageSize;

      // 查询用户应战的猜拳记录（已完成的）
      const [challenges, total] = await this.rpsRepository.findAndCount({
        where: {
          responderId: userId,
          status: 2, // COMPLETED状态
        },
        order: { created_at: "DESC" },
        skip: offset,
        take: pageSize,
      });

      // 转换数据格式以匹配前端期望的格式
      const records = challenges.map((challenge) => ({
        answer_id: userId,
        bet: challenge.betAmount,
        id: challenge.id,
        name: challenge.challengerName || "未知挑战者",
        state: this.getResponseResultState(challenge),
        type: challenge.currencyType,
        time: challenge.created_at.toISOString(),
        user_id: userId,
        value: challenge.responderValue || 0,
      }));

      return {
        act_id: 2106,
        code: 0,
        data: {
          list: records,
          total,
          page,
          pageSize,
        },
      };
    } catch (error: any) {
      this.logger.error("获取美人计响应记录失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取应战结果状态
   */
  private getResponseResultState(challenge: CasinoRockPaperScissors): number {
    if (!challenge.isCompleted || !challenge.hasWinner) {
      return 0; // 未完成
    }

    // 如果应战者获胜，返回1；如果挑战者获胜，返回2
    return challenge.winnerId === challenge.responderId ? 1 : 2;
  }

  /**
   * 获取美人计胜率排行榜 (act_id: 2108)
   */
  async getRPSWinRankings(page: number = 0) {
    try {
      // 实现胜率排行榜
      const pageSize = 10;
      const offset = page * pageSize;

      // TODO: 从数据库查询猜拳胜率排行榜
      // 这里先返回模拟数据，后续需要实现真实的数据库查询
      const mockRankings = [
        {
          money: 50000,
          name: "猜拳大师",
          userId: 1001,
          wintime: 150, // 获胜次数
        },
        {
          money: 35000,
          name: "石头剪刀布",
          userId: 1002,
          wintime: 120,
        },
        {
          money: 28000,
          name: "猜拳高手",
          userId: 1003,
          wintime: 95,
        },
        {
          money: 22000,
          name: "猜拳新手",
          userId: 1004,
          wintime: 78,
        },
        {
          money: 18000,
          name: "猜拳爱好者",
          userId: 1005,
          wintime: 65,
        },
      ];

      return {
        act_id: 2108,
        code: 0,
        data: {
          list: mockRankings,
          total: mockRankings.length,
          page,
          pageSize,
        },
      };
    } catch (error: any) {
      this.logger.error("获取美人计胜率排行榜失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取大小+赤壁玩法赢金排行榜 (act_id: 1340)
   */
  async getDiceWinAmountRankings(page: number = 0, limit: number = 50) {
    try {
      // 联合查询大小和赤壁玩法的赢金总额
      const offset = page * limit;
      const entityManager = this.betService["diceBetRepository"].manager;
      const sql = `
        SELECT
          t.characterId,
          t.userId,
          SUM(t.winGold) AS totalWinGold,
          MAX(c.name) AS characterName
        FROM (
          SELECT userId, winAmount AS winGold, characterId FROM casino_dice_bets WHERE status = 2 AND winAmount > 0
          UNION ALL
          SELECT userId, winGold AS winGold, characterId FROM casino_chibi_bets WHERE status = 2 AND winGold > 0
        ) t
        LEFT JOIN characters c ON t.characterId = c.id
        GROUP BY t.characterId, t.userId
        ORDER BY totalWinGold DESC
        LIMIT ? OFFSET ?
      `;
      const results = await entityManager.query(sql, [limit, offset]);

      // 组装排行榜数据
      const rankings = results.map((row: any) => {
        const totalWinAmount = parseInt(row.totalWinGold) || 0;
        let title = "赌徒";
        if (totalWinAmount >= 10000000) title = "赌神";
        else if (totalWinAmount >= 5000000) title = "赌圣";
        else if (totalWinAmount >= 1000000) title = "赌侠";
        else if (totalWinAmount >= 500000) title = "赌狂";
        else if (totalWinAmount >= 100000) title = "赌魔";
        else if (totalWinAmount >= 50000) title = "赌痴";
        else if (totalWinAmount >= 10000) title = "赌怪";
        else if (totalWinAmount >= 5000) title = "赌鬼";
        return {
          name: row.characterName || `玩家${row.userId}`,
          record: totalWinAmount,
          title,
          userid: row.userId,
        };
      });

      return {
        act_id: 1340,
        code: 0,
        list: rankings,
        type: 41,
      };
    } catch (error: any) {
      this.logger.error(
        "获取大小+赤壁玩法赢金排行榜失败:",
        error?.message || error
      );
      throw error;
    }
  }

  /**
   * 获取美人计盈利排行榜 (act_id: 2109)
   */
  async getRPSProfitRankings(page: number = 0) {
    try {
      // 实现盈利排行榜
      const pageSize = 10;
      const offset = page * pageSize;

      // TODO: 从数据库查询猜拳盈利排行榜
      // 这里先返回模拟数据，后续需要实现真实的数据库查询
      const mockRankings = [
        {
          money: 75000,
          name: "盈利之王",
          userId: 2001,
          wintime: 200, // 获胜次数
        },
        {
          money: 62000,
          name: "赚钱高手",
          userId: 2002,
          wintime: 180,
        },
        {
          money: 48000,
          name: "盈利达人",
          userId: 2003,
          wintime: 150,
        },
        {
          money: 35000,
          name: "赚钱新手",
          userId: 2004,
          wintime: 120,
        },
        {
          money: 28000,
          name: "盈利新手",
          userId: 2005,
          wintime: 95,
        },
      ];

      return {
        act_id: 2109,
        code: 0,
        data: {
          list: mockRankings,
          total: mockRankings.length,
          page,
          pageSize,
        },
      };
    } catch (error: any) {
      this.logger.error("获取美人计盈利排行榜失败:", error?.message || error);
      throw error;
    }
  }

  // ==================== 通用接口 ====================

  /**
   * 获取排行榜 (act_id: 1340)
   */
  async getRankings(gameType: GameType, rankingType: string, page: number = 0) {
    try {
      // TODO: 实现排行榜查询
      const mockRankings = {
        list: [
          { name: "玩家1", record: 10000, title: "赌神", userid: 1 },
          { name: "玩家2", record: 8000, title: "赌圣", userid: 2 },
        ],
        total: 2,
        page,
      };

      return {
        act_id: 1340,
        code: 0,
        data: mockRankings,
      };
    } catch (error: any) {
      this.logger.error("获取排行榜失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取系统统计信息
   */
  async getSystemStatistics() {
    try {
      const diceStats = await this.roundService.getRoundStatistics(
        GameType.DICE
      );
      const chibiStats = await this.roundService.getRoundStatistics(
        GameType.CHIBI
      );
      const settlementStats =
        await this.settlementService.getSettlementStatistics();

      return {
        dice: diceStats,
        chibi: chibiStats,
        settlement: settlementStats,
      };
    } catch (error: any) {
      this.logger.error("获取系统统计信息失败:", error?.message || error);
      throw error;
    }
  }

  // ==================== 管理接口 ====================

  /**
   * 手动创建期数
   */
  async createRoundManually(gameType: GameType) {
    try {
      const startTime = new Date();
      const endTime = new Date(startTime.getTime() + 10 * 60 * 1000); // 10分钟后结束

      const round = await this.roundService.createNewRound(
        gameType,
        startTime,
        endTime
      );
      return round;
    } catch (error: any) {
      this.logger.error("手动创建期数失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 手动结算期数
   */
  async settleRoundManually(roundId: number) {
    try {
      // 先尝试从大小玩法期数表获取
      let round = await this.roundService.getRoundInfo(roundId, GameType.DICE);
      let gameType = GameType.DICE;

      // 如果不在大小玩法表中，尝试从赤壁玩法期数表获取
      if (!round) {
        round = await this.roundService.getRoundInfo(roundId, GameType.CHIBI);
        gameType = GameType.CHIBI;
      }

      if (!round) {
        throw new Error("期数不存在");
      }

      switch (gameType) {
        case GameType.DICE:
          await this.settlementService.settleDiceRound(roundId);
          break;
        case GameType.CHIBI:
          await this.settlementService.settleChibiRound(roundId);
          break;
        default:
          throw new Error("不支持的游戏类型");
      }

      return { success: true, message: "结算成功" };
    } catch (error: any) {
      this.logger.error("手动结算期数失败:", error?.message || error);
      throw error;
    }
  }

  /**
   * 获取下注类型的中文描述
   */
  private getBetTypeDescription(betType: number): string {
    const betTypeName = getBetTypeName(betType as any);
    return `抽${betTypeName}`;
  }

  /**
   * 生成赤壁战报描述
   */
  private generateChibiReport(winningSide: number): string {
    const reports: Record<number, string> = {
      1: "魏军势如破竹，大获全胜！",
      2: "蜀军奇谋妙计，吴军溃不成军！",
      3: "吴军水师精锐，所向披靡！",
    };
    return reports[winningSide] || "战况激烈，胜负难分！";
  }
}
